using System;
using System.Collections;
using System.Reflection;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Linq;
using UnityEditor.Graphs;
using UnityEngine.UIElements;
using Codice.CM.Client.Gui;

namespace DT.Art.VFX.DTEditorGUI
{
    [Flags]
    public enum ChannelMode
    {
        none = 0,
        x = 1 << 0,
        y = 1 << 1,
        z = 1 << 2,
        w = 1 << 3
    };
    [Flags]
    public enum ChannelColMode
    {
        none = 0,
        R = 1 << 0,
        G = 1 << 1,
        B = 1 << 2,
        A = 1 << 3
    };
    public struct DTchannelDate
    {
        public float x;
        public float y;
        public float z;
        public float w;
        public DTchannelDate(float? x = null, float? y = null, float? z = null, float? w = null)
        {
            this.x = x ?? 0;
            this.y = y ?? 0;
            this.z = z ?? 0;
            this.w = w ?? 0;
        }
        public DTchannelDate(Color v)
        {
            this.x = v.r;
            this.y = v.g;
            this.z = v.b;
            this.w = v.a;
        }
        public DTchannelDate(Color32 v)
        {
            this.x = v.r / 255f;
            this.y = v.g / 255f;
            this.z = v.b / 255f;
            this.w = v.a / 255f;
        }
        public DTchannelDate(Vector4 v)
        {
            this.x = v.x;
            this.y = v.y;
            this.z = v.z;
            this.w = v.w;
        }
        public DTchannelDate(Vector3 v)
        {
            this.x = v.x;
            this.y = v.y;
            this.z = v.z;
            this.w = 0;
        }
        public DTchannelDate(Vector2 v)
        {
            this.x = v.x;
            this.y = v.y;
            this.z = 0;
            this.w = 0;
        }
        public DTchannelDate(MaterialProperty property)
        {
            if (property.type == MaterialProperty.PropType.Vector)
            {
                this.x = property.vectorValue.x;
                this.y = property.vectorValue.y;
                this.z = property.vectorValue.z;
                this.w = property.vectorValue.w;
            }
            else if (property.type == MaterialProperty.PropType.Texture)
            {
                this.x = property.textureScaleAndOffset.x;
                this.y = property.textureScaleAndOffset.y;
                this.z = property.textureScaleAndOffset.z;
                this.w = property.textureScaleAndOffset.w;
            }
            else if (property.type == MaterialProperty.PropType.Color)
            {
                this.x = property.colorValue.r;
                this.y = property.colorValue.g;
                this.z = property.colorValue.b;
                this.w = property.colorValue.a;
            }
            else if (property.type == MaterialProperty.PropType.Range || property.type == MaterialProperty.PropType.Float)
            {
                this.x = property.floatValue;
                this.y = property.floatValue;
                this.z = property.floatValue;
                this.w = property.floatValue;
            }
            else if (property.type == MaterialProperty.PropType.Int)
            {
                this.x = property.intValue;
                this.y = property.intValue;
                this.z = property.intValue;
                this.w = property.intValue;
            }
            else
            {
                this.x = 0;
                this.y = 0;
                this.z = 0;
                this.w = 0;
            }
        }

        public Vector4 ToVector4()
        {
            return new Vector4(x, y, z, w);
        }
        public Color ToColor()
        {
            return new Color(x, y, z, w);
        }

        public DTchannelDate Set(ChannelMode mode, params float[] val)
        {
            if (val.Length == 0) return this;

            int valIndex = 0;
            if (mode == ChannelMode.none)
            {
                x = val[0]; return this;
            }
            // 按照 x->y->z->w 的顺序处理，确保值的索引与通道顺序对应
            if (mode.HasFlag(ChannelMode.x) && valIndex < val.Length)
                x = val[valIndex++];
            if (mode.HasFlag(ChannelMode.y) && valIndex < val.Length)
                y = val[valIndex++];
            if (mode.HasFlag(ChannelMode.z) && valIndex < val.Length)
                z = val[valIndex++];
            if (mode.HasFlag(ChannelMode.w) && valIndex < val.Length)
                w = val[valIndex++];
            return this;
        }
        public DTchannelDate Setv2(ChannelMode mode, Vector2 val)
        {
            return Set(mode, val.x, val.y);
        }
        public DTchannelDate Setv3(ChannelMode mode, Vector3 val)
        {
            return Set(mode, val.x, val.y, val.z);
        }

        public int ToInt()
        {
            return (int)x;
        }
        public float ToFloat()
        {
            return x;
        }
        public int ToInt(ChannelMode mode)
        {
            return (int)ToFloat(mode);
        }
        public float ToFloat(ChannelMode mode)
        {
            switch (mode)
            {
                case ChannelMode.x: return x;
                case ChannelMode.y: return y;
                case ChannelMode.z: return z;
                case ChannelMode.w: return w;
                default: return x;
            }
        }
        public Vector2 ToVector2(ChannelMode mode)
        {
            float xVal = 0, yVal = 0;
            int valueCount = 0;

            // 按照 x->y->z->w 的优先顺序处理，确保选择前两个有效通道
            if (mode.HasFlag(ChannelMode.x) && valueCount < 2)
            {
                if (valueCount == 0) xVal = x;
                else yVal = x;
                valueCount++;
            }
            if (mode.HasFlag(ChannelMode.y) && valueCount < 2)
            {
                if (valueCount == 0) xVal = y;
                else yVal = y;
                valueCount++;
            }
            if (mode.HasFlag(ChannelMode.z) && valueCount < 2)
            {
                if (valueCount == 0) xVal = z;
                else yVal = z;
                valueCount++;
            }
            if (mode.HasFlag(ChannelMode.w) && valueCount < 2)
            {
                if (valueCount == 0) xVal = w;
                else yVal = w;
            }

            return new Vector2(xVal, yVal);
        }

        public Vector3 ToVector3(ChannelMode mode)
        {
            float xVal = 0, yVal = 0, zVal = 0;
            int valueCount = 0;

            // 按照 x->y->z->w 的优先顺序处理，确保选择前两个有效通道
            if (mode.HasFlag(ChannelMode.x) && valueCount < 3)
            {
                if (valueCount == 0) xVal = x;
                else if (valueCount == 1) yVal = x;
                else zVal = x;
                valueCount++;
            }
            if (mode.HasFlag(ChannelMode.y) && valueCount < 3)
            {
                if (valueCount == 0) xVal = y;
                else if (valueCount == 1) yVal = y;
                else zVal = y;
                valueCount++;
            }
            if (mode.HasFlag(ChannelMode.z) && valueCount < 3)
            {
                if (valueCount == 0) xVal = z;
                else if (valueCount == 1) yVal = z;
                else zVal = z;
                valueCount++;
            }
            if (mode.HasFlag(ChannelMode.w) && valueCount < 3)
            {
                if (valueCount == 0) xVal = w;
                else if (valueCount == 1) yVal = w;
                else zVal = w;
            }
            return new Vector3(xVal, yVal, zVal);
        }
        public override string ToString()
        {
            return $"DTchannelDate: (x:{x}, y:{y}, z:{z}, w:{w})";
        }
    }
    #region 常用函数
    #region  DT_HeaderScope 折叠区域
    public class DT_HeaderScope : IDisposable
    {
        public bool expanded { get; private set; }
        private Editor editor;
        private GUIContent text;
        public Rect BtnRect { get; private set; }
        public DT_HeaderScope(string headerText, bool initialExpanded, Editor targetEditor, int count = 0)
        {
            init(DTGUIEx.DTGetContent(headerText), initialExpanded, targetEditor, count);
        }
        public DT_HeaderScope(GUIContent headerGUIContent, bool initialExpanded, Editor targetEditor, int count = 0)
        {
            init(headerGUIContent, initialExpanded, targetEditor, count);
        }
        private void init(GUIContent headerContent, bool initialExpanded, Editor targetEditor, int count)
        {
            const float _height = 20f;
            text = headerContent;
            expanded = initialExpanded;
            editor = targetEditor;
            float backgroundTint = EditorGUIUtility.isProSkin ? 0.1f : 1f;
            // 开始绘制折叠区域
            var backgroundRect = GUILayoutUtility.GetRect(1, _height);
            var fixedRect = backgroundRect;
            if (count > 0)
                fixedRect.width = EditorGUIUtility.currentViewWidth - (20 * count + count * 2 - 2) - 40;
            var toogleRect = Rect.zero;
            if (count > 0)
            {
                toogleRect = backgroundRect;
                toogleRect.width = 20 * count + count * 2 - 2;
                toogleRect.x = EditorGUIUtility.currentViewWidth - (20 * count + count * 2 - 2);
                BtnRect = new Rect(toogleRect.x, toogleRect.y, toogleRect.width, toogleRect.height);
            }

            backgroundRect.xMin = 0f;
            EditorGUI.DrawRect(backgroundRect, new Color(backgroundTint, backgroundTint, backgroundTint, 0.2f));
            backgroundRect.height = 1;
            EditorGUI.DrawRect(backgroundRect, new Color(0, 0, 0, 0.2f));
            expanded = EditorGUI.BeginFoldoutHeaderGroup(fixedRect, expanded, text, new GUIStyle(EditorStyles.foldout)   //EditorStyles.foldout 
            {
                fontStyle = EditorStyles.boldLabel.fontStyle,
                fontSize = EditorStyles.boldLabel.fontSize,
                alignment = TextAnchor.MiddleLeft,
                fixedHeight = EditorStyles.toggle.fixedHeight,
                padding = new RectOffset(18, 0, 0, 0)
                // contentOffset = new Vector2(0, 2)
            });
            if (expanded)
            {
                var rect = EditorGUILayout.GetControlRect(true, 1);
                rect.xMin = 0f;
                rect.y -= 2;
                EditorGUI.DrawRect(rect, new Color(0, 0, 0, 0.3f));
                // EditorGUILayout.BeginVertical("box");
                EditorGUILayout.Space(1);
            }
        }
        public void Dispose()
        {
            // 结束折叠区域
            EditorGUI.EndFoldoutHeaderGroup();
            if (expanded)
            {
                EditorGUILayout.Space();
            }
            // 确保编辑器更新
            if (editor != null && GUI.changed)
            {
                EditorUtility.SetDirty(editor.target);
            }
        }
    }
    #endregion
    public static partial class DTUtil
    {
        const int bitMaxCount = 16 - 1; //16-bit,符号位保留
        public static bool GetBits(int srcVal, int position)
        {
            return GetBits(srcVal, position, 1) > 0;
        }
        public static int GetBits(int srcVal, int position, int length)
        {
            // 参数验证
            if (length <= 0 || position < 0 || position + length > bitMaxCount)
            { // 假设使用32位整数
                return srcVal;
                // throw new ArgumentOutOfRangeException("Invalid position or length for 32-bit integer");
            }
            // 创建一个掩码，用于提取指定长度的位
            int mask = (1 << length) - 1;
            return srcVal >> position & mask;
        }

        public static int ReplaceBits(int val, int srcVal, int position, int length)
        {
            // 参数验证
            if (length <= 0 || position < 0 || position + length > bitMaxCount)
            { // 假设使用32位整数
                return val;
                // throw new ArgumentOutOfRangeException("Invalid position or length for 32-bit integer");
            }

            // 创建一个掩码，用于提取a中指定长度的位
            int mask = (1 << length) - 1;

            // 创建一个清除掩码，用于清除b中指定位置的位
            int clearMask = ~(mask << position);

            // 确保a的值不会超过指定长度所能表示的范围
            int valueToInsert = val & mask;

            // 将a的值左移到指定位置
            valueToInsert = valueToInsert << position;

            // 清除b中指定位置的位，然后将a的值插入到该位置
            int result = (srcVal & clearMask) | valueToInsert;

            return result;
        }
        public static T TryGetDictVal<T>(this Dictionary<string, T> dict, string key, T defaultValue = default)
        {
            if (dict.TryGetValue(key, out T value))
            {
                return value;
            }
            else
            {
                return defaultValue;
            }
        }
        public static T ToEnum<T>(this string key, T defaultValue = default) where T : Enum
        {
            // 处理null或空字符串的情况
            if (string.IsNullOrEmpty(key))
                return defaultValue;

            try
            {
                return (T)Enum.Parse(typeof(T), key);
            }
            catch (ArgumentException)
            {
                // 匹配失败时返回默认值
                return defaultValue;
            }
        }
        // public static Texture ScaleTexture(Texture source, int targetWidth, int targetHeight)
        // {
        //     Texture2D result = new Texture2D(targetWidth, targetHeight, source.format, false);

        // }
        public static bool GetShaderKeywords(Shader target, out string[] global, out string[] local)
        {
            try
            {
                MethodInfo globalKeywords = typeof(ShaderUtil).GetMethod("GetShaderGlobalKeywords", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                global = (string[])globalKeywords.Invoke(null, new object[] { target });
                MethodInfo localKeywords = typeof(ShaderUtil).GetMethod("GetShaderLocalKeywords", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                local = (string[])localKeywords.Invoke(null, new object[] { target });
                return true;
            }
            catch
            {
                global = local = null;
                return false;
            }
        }
        public static void DTAddKey(this Dictionary<string, bool> expandBit, string key, bool value)
        {
            if (!expandBit.ContainsKey(key))
            {
                expandBit.Add(key, value);
            }
            else
            {
                expandBit[key] = value;
            }
        }
        public static void DTAddKey(this Dictionary<string, bool> expandBit, string key)
        {
            if (!expandBit.ContainsKey(key))
            {
                expandBit.Add(key, false);
            }
        }

        static Matrix4x4 halfMatr = new Matrix4x4
            (
            new Vector4(0.5f, 0.0f, 0.0f, 0.0f),
            new Vector4(0.0f, 0.5f, 0.0f, 0.0f),
            new Vector4(0.5f, 0.5f, 1.0f, 0.0f),
            new Vector4(0.0f, 0.0f, 0.0f, 1.0f)
            );

        // 先计算左边 3 个矩阵的乘积
        static Matrix4x4 CenterMatr = new Matrix4x4
        (
        new Vector4(2.0f, 0.0f, 0.0f, 0.0f),
        new Vector4(0.0f, 2.0f, 0.0f, 0.0f),
        new Vector4(-1.0f, -1.0f, 1.0f, 0.0f),
        new Vector4(0.0f, 0.0f, 0.0f, 1.0f)
        );

        private static Matrix4x4 CreateRotationMatrix(float _angle)
        {
            float angle = -1 * _angle * Mathf.Deg2Rad;
            float cosv = Mathf.Cos(angle);
            float sinv = Mathf.Sin(angle);
            Matrix4x4 rotMatr = new Matrix4x4
            (
                new Vector4(cosv, -sinv, 0.0f, 0.0f),
                new Vector4(sinv, cosv, 0.0f, 0.0f),
                new Vector4(0.0f, 0.0f, 1.0f, 0.0f),
                new Vector4(0.0f, 0.0f, 0.0f, 1.0f)
            );
            return rotMatr;
            return halfMatr * rotMatr * CenterMatr;
        }
        public static (Vector4, Vector4) SetUVMatr(Vector4 Tilingoffset, float _angle)
        {
            Vector2 til = new Vector2(Tilingoffset.x, Tilingoffset.y);
            Vector2 off = new Vector2(Tilingoffset.z, Tilingoffset.w);
            return SetUVMatr(til, off, _angle);
        }
        public static (Vector4, Vector4) SetUVMatr(Vector2 Tiling, Vector2 offset, float _angle)
        {
            // 这个计算旋转矩阵的注释是错误的，还需要以下面实际计算来重写
            // |0.5,0.0,0.5| |scx,0.0,ofx| |cos,-sin,0.0| |2.0,0.0,-1.0|
            // |0.0,0.5,0.5|*|0.0,scy,ofy|*|sin, cos,0.0|*|0.0,2.0,-1.0|
            // |0.0,0.0,1.0| |0.0,0.0,1.0| |0.0, 0.0,1.0| |0.0,0.0, 1.0|
            Matrix4x4 rotMatr = CreateRotationMatrix(_angle);
            // 计算变换矩阵
            Matrix4x4 tranMatr = new Matrix4x4
            (
              new Vector4(Tiling.x, 0.0f, 0.0f, 0.0f),
              new Vector4(0.0f, Tiling.y, 0.0f, 0.0f),
              new Vector4(-offset.x * 0, -offset.y * 0, 1.0f, 0.0f),
              new Vector4(0.0f, 0.0f, 0.0f, 1.0f)
            );
            Matrix4x4 ScaleMatr = new Matrix4x4
            (
              new Vector4(Tiling.x, 0.0f, 0.0f, 0.0f),
              new Vector4(0.0f, Tiling.y, 0.0f, 0.0f),
              new Vector4(0.0f, 0.0f, 1.0f, 0.0f),
              new Vector4(0.0f, 0.0f, 0.0f, 1.0f)
            );
            Matrix4x4 offsetMatr = new Matrix4x4
            (
              new Vector4(1.0f, 0.0f, 0.0f, 0.0f),
              new Vector4(0.0f, 1.0f, 0.0f, 0.0f),
              new Vector4(-offset.x, -offset.y, 1.0f, 0.0f),
              new Vector4(0.0f, 0.0f, 0.0f, 1.0f)
            );
            // Matrix4x4 finalResult = (halfMatr * tranMatr * CenterMatr) * rotMatr;
            // Matrix4x4 finalResult = ScaleMatr * offsetMatr * CenterMatr; //
            Matrix4x4 finalResult = halfMatr * rotMatr * ScaleMatr * offsetMatr * CenterMatr; //
            // 计算最终结果 
            Vector4 R1 = finalResult.GetRow(0);
            Vector4 R2 = finalResult.GetRow(1);
            R1.w = _angle;
            return (R1, R2);
        }
        public static (Vector2, Vector2, float) GetUVMatr(Vector4 r1, Vector4 r2)
        {
            Matrix4x4 finalResult = Matrix4x4.identity;
            finalResult.SetRow(0, new Vector4(r1.x, r1.y, r1.z, 0.0f));
            finalResult.SetRow(1, new Vector4(r2.x, r2.y, r2.z, 0.0f));
            float angle = r1.w;
            Matrix4x4 productMatrix = CreateRotationMatrix(angle);
            // 定义一个极小值用于判断行列式是否接近 0
            const float epsilon = 0.000001f;

            // 检查行列式是否接近 0
            if (Mathf.Abs(productMatrix.determinant) < epsilon)
            {
                Debug.LogError("矩阵不可逆，行列式接近 0。");
                return (Vector2.zero, Vector2.zero, angle);
            }
            Matrix4x4 inverseMatrix = productMatrix.inverse;
            // 左乘逆矩阵得到 tranMatr
            Matrix4x4 tranMatrInverse = finalResult * inverseMatrix;

            // 提取缩放和偏移值
            float scx = (float)Math.Round(tranMatrInverse.m00, 4);
            float scy = (float)Math.Round(tranMatrInverse.m11, 4);
            float ofx = (float)Math.Round(tranMatrInverse.m02, 4);
            float ofy = (float)Math.Round(tranMatrInverse.m12, 4);

            return (new Vector2(scx, scy), new Vector2(-ofx, -ofy), angle);
        }
    }
    #endregion

    #region 检查纹理错误
    public static class DTShaderGUIExtension
    {

        public static (int, int, string, string) CheckTexsError(this MaterialEditor materialEditor, MaterialProperty[] Prop)
        {
            int wcount = 0;
            int ecount = 0;
            string wtext = "";
            string etext = "";
            foreach (var item in Prop)
            {
                var (w, e, wt, et) = CheckTexError(materialEditor, item);
                wcount += w;
                ecount += e;
                wtext += "\n" + wt;
                etext += "\n" + et;
            }
            return (wcount, ecount, wtext, etext);
        }


        /// <summary>
        /// 检查纹理错误
        /// </summary>
        /// <param name="materialEditor"></param>
        /// <param name="Prop"></param>
        /// <returns> ( 警告数, 错误数, 警告信息, 错误信息) </returns>
        public static (int, int, string, string) CheckTexError(this MaterialEditor materialEditor, MaterialProperty Prop)
        {
            if (materialEditor == null)
                return (0, 0, "", "");
            Material material = materialEditor.target as Material;
            if (material == null)
                return (0, 0, "", "");
            if (Prop == null)
                return (0, 0, "", "");
            if (Prop.type != MaterialProperty.PropType.Texture)
            {
                return (0, 0, "", "");
            }
            Texture tex = Prop.textureValue;
            if (tex == null)
                return (0, 0, "", "");
            return CheckError(material, tex);
        }
        // Material material = materialEditor.target as Material;
        static (int, int, string, string) CheckError(Material material, Texture tex)
        {
            if (tex == null || material == null)
                return (0, 0, "", "");
            int wcount = 0;
            int ecount = 0;

            int BZ_size = 1024;
            int BZ_ErrorSize = 2048;

            string TexPath = AssetDatabase.GetAssetPath(tex);
            string MatePath = AssetDatabase.GetAssetPath(material);

            string ErrorText = "";
            string WarningText = "";
            int actualWidth = 0;
            int actualHeight = 0;

            // string processedTexPath = ProcessPath(TexPath);
            string processedMatePath = ProcessPath(MatePath);
            if (!TexPath.StartsWith(processedMatePath))
            {
                ErrorText += $"★★★====>路径有误.\n";
                ecount++;
            }

            string texFileName = System.IO.Path.GetFileNameWithoutExtension(TexPath);
            System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"^[a-zA-Z0-9_\-]+$");
            if (!regex.IsMatch(texFileName))
            {
                ErrorText += $"★★======>名字包含非法字符. \n";
                ecount++;
            }

            if (texFileName.Length > 20)
            {
                WarningText += $"★=======>图片名:长度超20个字符. \n";
                wcount++;
            }

            Texture2D t = tex as Texture2D;
            bool minmap = t.minimumMipmapLevel > 0;
            if (t != null)
            {
                actualWidth = t.width;
                actualHeight = t.height;

                // 获取 TextureImporter
                TextureImporter textureImporter = AssetImporter.GetAtPath(TexPath) as TextureImporter;
                if (textureImporter != null)
                {
#if UNITY_2020_2_OR_NEWER
                    // Unity 2020.2 及更高版本使用 GetWidthAndHeight 方法
                    textureImporter.GetSourceTextureWidthAndHeight(out actualWidth, out actualHeight);
#else
                    // 旧版本使用 maxTextureSize 属性
                    actualWidth = textureImporter.maxTextureSize;
                    actualHeight = textureImporter.maxTextureSize;
#endif
                    minmap = textureImporter.mipmapEnabled;
                }

                // isSizeError = ;
                if (actualWidth > BZ_size || actualHeight > BZ_size)
                {
                    if (actualWidth > BZ_ErrorSize || actualHeight > BZ_ErrorSize)
                    {
                        ErrorText += $"★=======>{actualWidth}x{actualHeight} > [{BZ_ErrorSize}X{BZ_ErrorSize}] \n";
                        ecount++;
                    }
                    else
                    {
                        WarningText += $"★=======>{actualWidth}x{actualHeight} > [{BZ_size}X{BZ_size}]  \n";
                        wcount++;
                    }

                }
                if (!isFourInt(actualWidth) || !isFourInt(actualHeight))
                {
                    string wt = isFourInt(actualWidth) ? "满足" : "不满足";
                    string ht = isFourInt(actualHeight) ? "满足" : "不满足";
                    ErrorText += $"★=======>4倍数: W:{wt} <=> H:{ht} \n";
                    ecount++;
                }
                if (t.isReadable)
                {
                    WarningText += $"★=======>Read/Write开启中... \n";
                    wcount++;
                }
                if (minmap)
                {
                    WarningText += $"★=======>开启Mipmap中... \n";
                    wcount++;
                }
            }
            int bhg = Mathf.CeilToInt(ecount * 0.5f);
            string texName = System.IO.Path.GetFileNameWithoutExtension(TexPath);
            string aaa = $"\n恭喜获得成就：倒反天罡!!!     作用:上传后，获得[不合格] X {bhg}枚";
            WarningText = $"警告: {texName} [{wcount}条]\n实际大小:[{actualWidth} X {actualHeight}] \n" + WarningText;
            ErrorText = $"错误: {texName} [{ecount}条] {aaa}\n实际大小:[{actualWidth} X {actualHeight}] \n" + ErrorText;

            return (wcount, ecount, WarningText, ErrorText);
        }

        private static bool isFourInt(float v)
        {
            const float epsilon = 0.0001f; // 定义一个误差范围
            return Math.Abs(v % 4) < epsilon;
        }

        public static string ProcessPath(string path)
        {
            string directoryPath = System.IO.Path.GetDirectoryName(path);
            string[] pathParts = directoryPath.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
            if (pathParts.Length > 0)
            {
                string lastPart = pathParts[pathParts.Length - 1].ToLower();
                if (lastPart == "material" || lastPart == "materials")
                {
                    pathParts = pathParts.Take(pathParts.Length - 1).ToArray();
                }
            }
            return string.Join("/", pathParts);
        }
    }
    #endregion

}